/*
 *
 *
Copyright (c) 1998-2001 Aristar, Inc. All rights reserved.

Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:

1. Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.

2. Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.

3. The end-user documentation included with the redistribution, if any,
must include the following acknowledgment:

"This product includes software developed by Aristar, Inc. (http://www.aristar.com/)."

Alternately, this acknowledgment may appear in the software itself, if and
wherever such third-party acknowledgments normally appear.

4. The names "Dialect" and "Aristar, Inc." must not be used to endorse or
promote products derived from this software without prior written permission.
For written permission, please contact info@aristar.com.

5. Products derived from this software may not be called "Dialect", nor may
"Dialect" appear in their name, without prior written permission of Aristar, Inc.

THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESSED OR IMPLIED WARRANTIES,
INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
ARISTAR, INC. OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

This software consists of voluntary contributions made by many individuals
on behalf of Aristar, Inc.  For more information on Aristar, Inc.,
please see <http://www.aristar.com/>.

Portions of this software are based upon software freely available and
written by individuals not associated with Aristar, Inc.  Copyrights are
maintained in the relevant source code files.
 *
 *
 */

// MainFrm.cpp : implementation of the CMainFrame class
//

#include "stdafx.h"
#include "DialectApp.h"

#ifdef IDE_SUPPORT

#include "MainFrm.h"
#include "DialectView.h"
#include "CodeEditWnd.h"
#ifndef DIALECT_LITE
#	include "MakeExeDlg.h"
#endif

#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif

extern void CloseDefaultOut();
extern void BackgroundHandler(CInterpreter* pInterp);
extern void SplitFullPath(CString input, CString& directory, CString& filename);

VALUE g_ModNameToView;	// Frame {moduleName:(int)CDialectView*}
VALUE g_FilenameToView;	// Frame {filenameName:(int)CDialectView*}

static void DebugOutFunc(CString text)
{
	((CMainFrame*)AfxGetMainWnd())->m_DebugOutDlg.AddDebugString(text);
}

/////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////
//	View handling code to help merge SDI/MDI differences

#ifdef __MDI__
#	define CURRENT_DIALECT_VIEW	((CDialectView*)MDIGetActive())
#else
#	define CURRENT_DIALECT_VIEW	m_pCurrentDialectView
#endif

void CMainFrame::ActivateDialectView(CDialectView* pView)
{
	// Bring the view to the front and give it the focus
	// pView of NULL is meaningless, except clears the CE variable
	#ifdef __MDI__
		if (pView != NULL) {
			MDIActivate(pView);
			pView->SetFocus();	// Hack line
		}
	#else
		if (m_pCurrentDialectView && ::IsWindow(m_pCurrentDialectView->m_hWnd)) {
			m_pCurrentDialectView->ShowWindow(SW_HIDE);
		}

		if ((pView != NULL) && (pView->GetSafeHwnd() != NULL)) {
			SetWindowText(pView->GetModuleName());
			::SetWindowPos(pView->m_hWnd, HWND_TOP, 0, 0, 0, 0,
				SWP_SHOWWINDOW | SWP_NOMOVE | SWP_NOSIZE);

			//MessageBeep(0);
			pView->SetFocus();
			//MessageBeep(0);
			//pView->m_CodeEditWnd.SetFocus();
		}
		m_pCurrentDialectView = pView;
	#endif
}

CDialectView* CMainFrame::NewDialectView()
{
	CDialectView* pView = new CDialectView();

#ifndef __MDI__
	RECT rc;
	GetClientRect(&rc);
	#if defined(UNDER_CE)
		if (m_hCommandBar != NULL) {
			#if !defined(WIN32_PLATFORM_PSPC) || (defined(WIN32_PLATFORM_PSPC) && (UNDER_CE >= 300))
				RECT rcCommandBar;
				::GetClientRect(m_hCommandBar, &rcCommandBar);
				rc.top += rcCommandBar.bottom - rcCommandBar.top;
			#endif
		}
	#else
		// Quick hack just for testing
		RECT rcToolBar;
		if (::IsWindow(m_wndToolBar.m_hWnd)) {
			m_wndToolBar.GetClientRect(&rcToolBar);
			rc.top += rcToolBar.bottom - rcToolBar.top;
		}
	#endif
	pView->Create(NULL, NULL, WS_VISIBLE | WS_CHILD, rc, this, 0);
	m_DialectViewList.AddTail(pView);
	ActivateDialectView(pView);
#else
	// load the frame
	CCreateContext context;
	context.m_pCurrentFrame = this;

	if (!pView->LoadFrame(IDR_DIALECTYPE, WS_OVERLAPPEDWINDOW | FWS_ADDTOTITLE,
		NULL, &context))
	{
		TRACE0("Couldn't load frame window.\n");
		delete pView;
		return NULL;
	}

	// set the handles and redraw the frame and parent
	CDialectApp* app = (CDialectApp*)AfxGetApp();
	pView->SetHandles(app->m_hMDIMenu, app->m_hMDIAccel);
	pView->InitialUpdateFrame(NULL, TRUE);
#endif
	return pView;
}

/*CDialectView* CMainFrame::FindFirstView()
{

}

CDialectView* CMainFrame::FindNextView()
{

}*/

/////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////
// CMainFrame

#ifdef __MDI__
IMPLEMENT_DYNAMIC(CMainFrame, BASEFRAMEWND)
#else
IMPLEMENT_DYNCREATE(CMainFrame, BASEFRAMEWND)
#endif

BEGIN_MESSAGE_MAP(CMainFrame, BASEFRAMEWND)
	// All ON_COMMAND_RANGE must be outside the below AFX message map area
	ON_COMMAND_RANGE(ID_WINDOW_FIRST, ID_WINDOW_LAST, OnWindowSelect)

	//{{AFX_MSG_MAP(CMainFrame)
	ON_COMMAND(ID_FILE_CLOSE, OnFileClose)
	ON_UPDATE_COMMAND_UI(ID_FILE_CLOSE, OnUpdateFileClose)
	ON_WM_CREATE()
	ON_COMMAND(ID_PROJECT_RUN, OnProjectRun)
	ON_UPDATE_COMMAND_UI(ID_PROJECT_RUN, OnUpdateProjectRun)
	ON_COMMAND(ID_PROJECT_SINGLESTEP, OnProjectSinglestep)
	ON_UPDATE_COMMAND_UI(ID_PROJECT_SINGLESTEP, OnUpdateProjectSinglestep)
	ON_COMMAND(ID_FILE_SAVE, OnFileSave)
	ON_COMMAND(ID_FILE_OPEN, OnFileOpen)
	ON_COMMAND(ID_FILE_NEW, OnFileNew)
	ON_COMMAND(ID_FILE_SAVE_AS, OnFileSaveAs)
	ON_UPDATE_COMMAND_UI(ID_FILE_SAVE, OnUpdateFileSave)
	ON_UPDATE_COMMAND_UI(ID_FILE_SAVE_AS, OnUpdateFileSaveAs)
	ON_COMMAND(ID_PROJECT_CONTINUE, OnProjectContinue)
	ON_UPDATE_COMMAND_UI(ID_PROJECT_CONTINUE, OnUpdateProjectContinue)
	ON_COMMAND(ID_PROJECT_PAUSE, OnProjectPause)
	ON_UPDATE_COMMAND_UI(ID_PROJECT_PAUSE, OnUpdateProjectPause)
	ON_COMMAND(ID_PROJECT_ABORT, OnProjectAbort)
	ON_COMMAND(ID_VIEW_LINENUMBERS, OnViewLineNumbers)
	ON_UPDATE_COMMAND_UI(ID_VIEW_LINENUMBERS, OnUpdateViewLineNumbers)
	ON_WM_CLOSE()
	ON_COMMAND(ID_PROJECT_STEPINTO, OnProjectStepinto)
	ON_UPDATE_COMMAND_UI(ID_PROJECT_STEPINTO, OnUpdateProjectStepinto)
	ON_COMMAND(ID_PROJECT_STEPOUT, OnProjectStepout)
	ON_UPDATE_COMMAND_UI(ID_PROJECT_STEPOUT, OnUpdateProjectStepout)
	ON_COMMAND(ID_FILE_PRINT, OnFilePrint)
	ON_UPDATE_COMMAND_UI(ID_FILE_PRINT, OnUpdateFilePrint)
	ON_UPDATE_COMMAND_UI(ID_PROJECT_ABORT, OnUpdateProjectAbort)
	ON_WM_SETFOCUS()
	ON_WM_KEYDOWN()
	ON_COMMAND(ID_WINDOW_NEXT, OnWindowNext)
	ON_COMMAND(ID_WINDOW_PREVIOUS, OnWindowPrevious)
	ON_COMMAND(ID_EDIT_FIND, OnEditFind)
	ON_UPDATE_COMMAND_UI(ID_EDIT_FIND, OnUpdateEditFind)
	ON_COMMAND(ID_EDIT_FINDNEXT, OnEditFindnext)
	ON_UPDATE_COMMAND_UI(ID_EDIT_FINDNEXT, OnUpdateEditFindnext)
	ON_COMMAND(ID_PROJECT_AUTOSAVEALLONRUN, OnProjectAutosaveallonrun)
	ON_UPDATE_COMMAND_UI(ID_PROJECT_AUTOSAVEALLONRUN, OnUpdateProjectAutosaveallonrun)
	ON_COMMAND(ID_PROJECT_CLEARDEFAULTMAINMODULE, OnProjectCleardefaultmainmodule)
	ON_UPDATE_COMMAND_UI(ID_PROJECT_CLEARDEFAULTMAINMODULE, OnUpdateProjectCleardefaultmainmodule)
	ON_COMMAND(ID_PROJECT_SETDEFAULTMAINMODULE, OnProjectSetdefaultmainmodule)
	ON_UPDATE_COMMAND_UI(ID_PROJECT_SETDEFAULTMAINMODULE, OnUpdateProjectSetdefaultmainmodule)
	ON_COMMAND(ID_FILE_SAVEALL, OnFileSaveall)
	ON_COMMAND(ID_PROJECT_MAKEEXE, OnProjectMakeexe)
	ON_COMMAND(ID_PROJECT_INSERTBREAKPOINT, OnProjectInsertbreakpoint)
	ON_COMMAND(ID_EDIT_COPY, OnEditCopy)
	ON_UPDATE_COMMAND_UI(ID_EDIT_COPY, OnUpdateEditCopy)
	ON_COMMAND(ID_EDIT_CUT, OnEditCut)
	ON_UPDATE_COMMAND_UI(ID_EDIT_CUT, OnUpdateEditCut)
	ON_COMMAND(ID_EDIT_DELETE, OnEditDelete)
	ON_UPDATE_COMMAND_UI(ID_EDIT_DELETE, OnUpdateEditDelete)
	ON_COMMAND(ID_EDIT_PASTE, OnEditPaste)
	ON_UPDATE_COMMAND_UI(ID_EDIT_PASTE, OnUpdateEditPaste)
	ON_COMMAND(ID_EDIT_REDO, OnEditRedo)
	ON_UPDATE_COMMAND_UI(ID_EDIT_REDO, OnUpdateEditRedo)
	ON_COMMAND(ID_EDIT_SELECTALL, OnEditSelectall)
	ON_COMMAND(ID_EDIT_UNDO, OnEditUndo)
	ON_UPDATE_COMMAND_UI(ID_EDIT_UNDO, OnUpdateEditUndo)
	ON_COMMAND(ID_VIEW_DEBUGOUT, OnViewDebugout)
	ON_UPDATE_COMMAND_UI(ID_VIEW_DEBUGOUT, OnUpdateViewDebugout)
	ON_WM_ACTIVATE()
	ON_COMMAND(ID_EDIT_COMMENTOUT, OnEditCommentOut)
	ON_UPDATE_COMMAND_UI(ID_EDIT_COMMENTOUT, OnUpdateEditCommentOut)
	ON_COMMAND(ID_EDIT_UNCOMMENT, OnEditUncomment)
	ON_UPDATE_COMMAND_UI(ID_EDIT_UNCOMMENT, OnUpdateEditUncomment)
	ON_COMMAND(ID_EDIT_INDENT, OnEditIndent)
	ON_UPDATE_COMMAND_UI(ID_EDIT_INDENT, OnUpdateEditIndent)
	ON_COMMAND(ID_EDIT_UNINDENT, OnEditUnindent)
	ON_UPDATE_COMMAND_UI(ID_EDIT_UNINDENT, OnUpdateEditUnindent)
	//}}AFX_MSG_MAP
END_MESSAGE_MAP()


#ifdef UNDER_CE
static TBBUTTON g_tbSTDButton[] = {
	{0,  0,				TBSTATE_ENABLED, TBSTYLE_SEP,    0, 0, 0,  0},
	{0,	 ID_FILE_NEW,	TBSTATE_ENABLED, TBSTYLE_BUTTON, 0, 0, 0, -1},
	{1,  ID_FILE_OPEN,	TBSTATE_ENABLED, TBSTYLE_BUTTON, 0, 0, 0, -1},
	{2,  ID_FILE_SAVE,	TBSTATE_ENABLED, TBSTYLE_BUTTON, 0, 0, 0, -1},
	{0,  0,				TBSTATE_ENABLED, TBSTYLE_SEP,    0, 0, 0, -1},
	{3,  ID_EDIT_CUT,	TBSTATE_ENABLED, TBSTYLE_BUTTON, 0, 0, 0, -1},
	{4,  ID_EDIT_COPY,	TBSTATE_ENABLED, TBSTYLE_BUTTON, 0, 0, 0, -1},
	{5,  ID_EDIT_PASTE,	TBSTATE_ENABLED, TBSTYLE_BUTTON, 0, 0, 0, -1},
	{0,  0,				TBSTATE_ENABLED, TBSTYLE_SEP,    0, 0, 0, -1},
	{7,  ID_PROJECT_RUN,		TBSTATE_ENABLED, TBSTYLE_BUTTON, 0, 0, 0, -1},
	{8,	 ID_PROJECT_CONTINUE,	TBSTATE_ENABLED, TBSTYLE_BUTTON, 0, 0, 0, -1},
	{9,	 ID_PROJECT_PAUSE,		TBSTATE_ENABLED, TBSTYLE_BUTTON, 0, 0, 0, -1},
	{10, ID_PROJECT_ABORT,		TBSTATE_ENABLED, TBSTYLE_BUTTON, 0, 0, 0, -1},
	{0,  0,						TBSTATE_ENABLED, TBSTYLE_SEP,    0, 0, 0, -1},
	{11, ID_PROJECT_STEPINTO,	TBSTATE_ENABLED, TBSTYLE_BUTTON, 0, 0, 0, -1},
	{12, ID_PROJECT_SINGLESTEP,	TBSTATE_ENABLED, TBSTYLE_BUTTON, 0, 0, 0, -1},
	{13, ID_PROJECT_STEPOUT,	TBSTATE_ENABLED, TBSTYLE_BUTTON, 0, 0, 0, -1},
	{0,  0,						TBSTATE_ENABLED, TBSTYLE_SEP,    0, 0, 0,  0}
};
#else
static UINT indicators[] =
{
	ID_SEPARATOR,           // status line indicator
	ID_INDICATOR_CAPS,
	ID_INDICATOR_NUM,
	ID_INDICATOR_SCRL,
};
#endif

/////////////////////////////////////////////////////////////////////////////
// CMainFrame construction/destruction

CMainFrame::CMainFrame()
{
	g_ModNameToView = AllocFrame(97);
	g_FilenameToView = AllocFrame(97);
	m_StepLevel = -1;
	m_bRunning = false;
	m_bSaveAllOnRun = AfxGetApp()->GetProfileInt(_T("Options"), _T("SaveAllOnRun"), 0) != 0;
	m_MainModule = AfxGetApp()->GetProfileString(_T("Options"), _T("LastMainModule"), _T(""));

#ifndef __MDI__
	m_pCurrentDialectView = NULL;
#endif
}

CMainFrame::~CMainFrame()
{
	g_Interpreter.Reset();
}

int CMainFrame::OnCreate(LPCREATESTRUCT lpCreateStruct)
{
	if (BASEFRAMEWND::OnCreate(lpCreateStruct) == -1)
		return -1;

	// Create the debug out dialog, intially invisible
	m_DebugOutDlg.Create(CDebugOutDlg::IDD, this);

#ifdef UNDER_CE
	// Add the buttons to the CommandBar.
	// NOTE: In order for AddAdornments() to work properly, NImages must be
	//       the true number of button images in the bitmap file (even if not
	//       all of them are used).
	if (!InsertButtons( g_tbSTDButton,
		sizeof(g_tbSTDButton)/sizeof(TBBUTTON),		// NButtons
		IDR_MAINFRAME,					// toolbar bitmap
		14))						// NImages
	{
		TRACE0("Failed to add command bar buttons\n");
		return -1;
	}

	// Add Exit and Help buttons
	//if (!AddAdornments(0)) {
	//	TRACE0("Failed to add exit and help buttons\n");
	//	return -1;
	//}
#else
	if (!m_wndToolBar.Create(this,
		WS_CHILD | WS_VISIBLE | CBRS_TOP | CBRS_TOOLTIPS | CBRS_FLYBY | CBRS_SIZE_DYNAMIC) ||
		!m_wndToolBar.LoadToolBar(IDR_MAINFRAME))
	{
		TRACE0("Failed to create toolbar\n");
		return -1;      // fail to create
	}

	if (!m_wndStatusBar.Create(this) ||
		!m_wndStatusBar.SetIndicators(indicators,
		  sizeof(indicators)/sizeof(UINT)))
	{
		TRACE0("Failed to create status bar\n");
		return -1;      // fail to create
	}

	m_wndToolBar.EnableDocking(CBRS_ALIGN_ANY);
	EnableDocking(CBRS_ALIGN_ANY);
	DockControlBar(&m_wndToolBar);
#endif

	return 0;
}

BOOL CMainFrame::PreCreateWindow(CREATESTRUCT& cs)
{
	if( !BASEFRAMEWND::PreCreateWindow(cs) )
		return FALSE;

#ifdef __MDI__
	cs.style |= (WS_HSCROLL | WS_VSCROLL);	// Scroll MDI area
#endif

	return TRUE;
}

/////////////////////////////////////////////////////////////////////////////
// CMainFrame diagnostics

#ifdef _DEBUG
void CMainFrame::AssertValid() const
{
	BASEFRAMEWND::AssertValid();
}

void CMainFrame::Dump(CDumpContext& dc) const
{
	BASEFRAMEWND::Dump(dc);
}

#endif //_DEBUG

/////////////////////////////////////////////////////////////////////////////
// CMainFrame message handlers

void CMainFrame::OnFileClose()
{
	// To close the child frame, just send a WM_CLOSE, which is the equivalent
	// choosing close from the system menu.
	CDialectView* pView = CURRENT_DIALECT_VIEW;
	if (pView != NULL) {
		pView->SendMessage(WM_CLOSE);
#ifndef __MDI__
		if (!::IsWindow(pView->m_hWnd)) {
			// The user did allow the window to close...
			POSITION p = m_DialectViewList.Find(pView);
			m_DialectViewList.RemoveAt(p);
			delete pView;
			OnWindowNext();	// Activate the next window
			UpdateWindowMenu();
		}
#endif
	}
}

void CMainFrame::OnUpdateFileClose(CCmdUI* pCmdUI)
{
	pCmdUI->Enable(CURRENT_DIALECT_VIEW != NULL);
}

void CMainFrame::OnProjectRun()
{
	// Careful, keep an eye on the bRestart variable :)
	static bool bRestart = false;
	//static bool bRunning = false;

	if (m_bRunning) {
		int i = MessageBox(_T("The program is currently running. Do you wish to restart the program?"),_T("Run"),MB_YESNO);
		if (i != IDYES)	return;
		else {
			g_Interpreter.Abort();
			bRestart = true;
			m_Step = stepRun;	// Get out of breakpoint loop (if in it)
			m_StepLevel = -1;
			return;	// Return to allow exiting of any background message handlers
		}
	}

	CDialectView* pChild = CURRENT_DIALECT_VIEW;
	if (!m_MainModule.IsEmpty()) {
		pChild = (CDialectView*)(g_ModNameToView.Get(m_MainModule).Integer());
	}

	if (pChild == NULL) {
		m_MainModule.Empty();
		pChild = CURRENT_DIALECT_VIEW;
	}

	if (pChild != NULL) {
		if (!SaveAllButCurrentView()) return;	// Use canceled during save request
		g_Interpreter.SetBreakPointFunc(BreakpointFunc);
		CString text = pChild->GetText();
		CString moduleName = pChild->GetModuleName();
		VALUE vContext = AllocFrame();
		CString initDir = ((CDialectApp*)AfxGetApp())->GetInitialPath();
		if (initDir.IsEmpty()) {
			CString initFilename;
			pChild->GetFileInfo(initDir, initFilename);
		}
		do {
			CloseDefaultOut();	// Closes previous default output window (in Dialect.cpp)
			g_Interpreter.Reset();
			g_Interpreter.SetInitialPath(initDir);
			m_Step = stepRun;
			m_StepLevel = -1;
			bRestart = false;
			m_DebugOutDlg.ClearDebugOutput();
			g_Interpreter.SetDebugOutFunc(DebugOutFunc);
			SetMessageText(_T("Running..."));
			m_bRunning = true;
			if (!g_Interpreter.InterpretText(text, vContext, moduleName)) {
				DisplayError(g_Interpreter.GetException());
				//VALUE v = g_Interpreter.GetException();
				//CString err = v[_T("msg")].String() + _T("\r\n") + v[_T("callstack")].String();
				//MessageBox(err, _T("Error"), MB_OK);
			}
			m_bRunning = false;
			if (::IsWindow(m_hWnd)) {	// If quit while in breakpoint loop, m_hWnd is invalid
				SetMessageText(_T(""));
				if (g_Interpreter.GetOpenWindows() <= 0) {
					// Reset will close a print preview window
					// Since the IDE is open here, the user probably doesn't
					// want the preview window to vanish instantly.
					// This window count is different from that used in gui module.
					g_Interpreter.Reset();
				}
			}
		} while (bRestart);
	}
}

void CMainFrame::OnUpdateProjectRun(CCmdUI* pCmdUI)
{
	pCmdUI->Enable(!m_bRunning && (CURRENT_DIALECT_VIEW != NULL));
}

/////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////
// Breakpoint handling routines...

/*static*/ void CMainFrame::BreakpointFunc(CString module, int line, CInterpreter * pInterp)
{
	CMainFrame* pFrame = (CMainFrame*)AfxGetMainWnd();
	if (pFrame && ::IsWindow(pFrame->m_hWnd)) {
		pFrame->_BreakpointFunc(module, line, pInterp);
	}
}

void CMainFrame::_BreakpointFunc(CString module, int line, CInterpreter * pInterp)
{
	// Enter breakpoint loop if:
	//		1. m_Step != stepRun, or
	//		2. IsBreakpoint(module, line)

	int stepLevel = pInterp->GetStackLevel();
	CDialectView* pChild = (CDialectView*)(g_ModNameToView.Get(module).Integer());

	//CString temp;
	//temp.Format(_T("Module: %s, Line: %d, pChild: %x"), (LPCTSTR)module, line, pChild);
	//MessageBox(temp);

	if (m_Step == stepRun) {
		if (pChild == NULL) return;	// Can't have a breakpoint if it's not open!
		else if(!pChild->m_CodeEditWnd.IsBreakpoint(line - 1)) return;
	}
	else if (m_Step == stepSingle) {
		if (stepLevel > m_StepLevel) return;
	}
	else if (m_Step == stepOut) {
		if (stepLevel >= m_StepLevel) return;
	}
	else if (m_Step == stepInto) {
		// No need to return...
	}

	if (pChild == NULL) {
		// This module isn't loaded in a text editor window, try and find it
		// and load if found...
		CString path = pInterp->CurrentModulePath();
		if (!path.IsEmpty() && TFile::Exists(path + module + _T(".d"))) {
			pChild = NewDialectView();
			if ((pChild != NULL) && !pChild->Open(path, module + _T(".d"))) {
				delete pChild;
				pChild = NULL;
			}
			else {
				// This will slow it down!
				UpdateWindowMenu();
				AfxGetApp()->AddToRecentFileList(CURRENT_DIALECT_VIEW->GetFilename());
			}
		}
	}

	// If pChild is still NULL, then it doesn't make sense to actually
	// enter the break loop, does it?  Since we have no window to show
	// the breakpoint line in.  Since we haven't changed m_Step, we will
	// still stop at the next possible chance (where a code window exists)
	if (pChild == NULL) return;

	SetCapture();		// Grab mouse away from possible gui.window
	ReleaseCapture();	// Let mouse be free to be you and me
	ActivateDialectView(pChild);	// Bring to front
	pChild->m_CodeEditWnd.SetCurrentLineMark(line - 1);
	m_StepLevel = stepLevel;	// Store for next time
	BreakpointLoop();
	if ((pChild != NULL) && ::IsWindow(pChild->m_hWnd)) {
		pChild->m_CodeEditWnd.SetCurrentLineMark(-1);	// Turn off mark
	}
}

void CMainFrame::BreakpointLoop()
{
	m_Step = stepPause;
	while (m_Step == stepPause)	{
		if (!AfxGetApp()->PumpMessage()) {
			::PostQuitMessage(0);
			g_Interpreter.Abort();
			return;
		}
		LONG lIdle = 0;
		while (AfxGetApp()->OnIdle(lIdle++));
	}
}

CDialectView* CMainFrame::IsBreakpoint(CString module, int line)
{
	CDialectView* pChild = (CDialectView*)(g_ModNameToView.Get(module).Integer());
	if (pChild == NULL) {
		return NULL;
	}
	else {
		return pChild->m_CodeEditWnd.IsBreakpoint(line - 1) ? pChild : NULL;
	}
}

void CMainFrame::OnProjectSinglestep()
{
	m_Step = stepSingle;
}

void CMainFrame::OnUpdateProjectSinglestep(CCmdUI* pCmdUI)
{
	pCmdUI->Enable(g_Interpreter.InBreakpoint());
}

void CMainFrame::OnProjectStepinto()
{
	m_Step = stepInto;
}

void CMainFrame::OnUpdateProjectStepinto(CCmdUI* pCmdUI)
{
	pCmdUI->Enable(g_Interpreter.InBreakpoint());
}

void CMainFrame::OnProjectStepout()
{
	m_Step = stepOut;
}

void CMainFrame::OnUpdateProjectStepout(CCmdUI* pCmdUI)
{
	pCmdUI->Enable(g_Interpreter.InBreakpoint());
}

void CMainFrame::OnProjectContinue()
{
	m_Step = stepRun;
}

void CMainFrame::OnUpdateProjectContinue(CCmdUI* pCmdUI)
{
	pCmdUI->Enable(g_Interpreter.InBreakpoint());
}


void CMainFrame::OnProjectPause()
{
	m_Step = stepPause;
}

void CMainFrame::OnUpdateProjectPause(CCmdUI* pCmdUI)
{
	pCmdUI->Enable(m_bRunning && !g_Interpreter.InBreakpoint());
}

void CMainFrame::OnProjectAbort()
{
	g_Interpreter.Abort();
	m_Step = stepRun;
}

void CMainFrame::OnUpdateProjectAbort(CCmdUI* pCmdUI)
{
	pCmdUI->Enable(m_bRunning);
}

/*void CMainFrame::OnViewExpressiondialog()
{
	if (::IsWindow(m_ExpressionDlg.m_hWnd)) {
		m_ExpressionDlg.Show(!m_ExpressionDlg.IsWindowVisible());
	}
	else {
		m_ExpressionDlg.Show(true);
	}
}*/

/*void CMainFrame::OnUpdateViewExpressiondialog(CCmdUI* pCmdUI)
{
	if (::IsWindow(m_ExpressionDlg.m_hWnd)) {
		pCmdUI->SetCheck(m_ExpressionDlg.IsWindowVisible());
	}
}*/

bool CMainFrame::Find(CString text, bool bMatchCase)
{
	CDialectView* pCurrent = CURRENT_DIALECT_VIEW;
	if (pCurrent != NULL) {
		return pCurrent->Find(text, bMatchCase);
	}
	return false;
}

void CMainFrame::OnEditFind()
{
	if (::IsWindow(m_FindDlg.m_hWnd)) {
		m_FindDlg.Show(!m_FindDlg.IsWindowVisible());
	}
	else {
		m_FindDlg.Show(true);
	}
}

void CMainFrame::OnUpdateEditFind(CCmdUI* pCmdUI)
{
	if (::IsWindow(m_FindDlg.m_hWnd)) {
		pCmdUI->SetCheck(m_FindDlg.IsWindowVisible());
	}
}

void CMainFrame::OnEditFindnext()
{
	if (::IsWindow(m_FindDlg.m_hWnd)) {
		Find(m_FindDlg.m_Text, m_FindDlg.m_bMatchCase == TRUE);
	}
}

void CMainFrame::OnUpdateEditFindnext(CCmdUI* pCmdUI)
{
	pCmdUI->Enable(::IsWindow(m_FindDlg.m_hWnd)	&& !m_FindDlg.m_Text.IsEmpty());
}

/////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////

void CMainFrame::OnClose()
{
	g_Interpreter.Abort();
	m_Step = stepRun;

#ifdef __MDI__
	CDialectView* pChild = CURRENT_DIALECT_VIEW;
	while (pChild != NULL) {
		//pChild->SendMessage(WM_CLOSE);	// Will allow saving files first
		if (!pChild->Save(true)) return;	// User canceled (in a save as dialog)
		pChild->DestroyWindow();
		pChild = CURRENT_DIALECT_VIEW;
	}
#else
	while(!m_DialectViewList.IsEmpty()) {
		CDialectView* pView = (CDialectView*)m_DialectViewList.GetHead();
		ActivateDialectView(pView);
		if (!pView->Save(true)) {
			UpdateWindowMenu();
			return;
		}
		delete (CDialectView*)m_DialectViewList.RemoveHead();
	}
	m_pCurrentDialectView = NULL;
#endif
	BASEFRAMEWND::OnClose();
}

void CMainFrame::OnFileSave()
{
	CURRENT_DIALECT_VIEW->Save(false);
	AfxGetApp()->AddToRecentFileList(CURRENT_DIALECT_VIEW->GetFilename());
	UpdateWindowMenu();
}

void CMainFrame::OnFileSaveAs()
{
	CURRENT_DIALECT_VIEW->SaveAs();
	AfxGetApp()->AddToRecentFileList(CURRENT_DIALECT_VIEW->GetFilename());
	UpdateWindowMenu();
}

void CMainFrame::OnUpdateFileSave(CCmdUI* pCmdUI)
{
	pCmdUI->Enable(CURRENT_DIALECT_VIEW != NULL);
}

void CMainFrame::OnUpdateFileSaveAs(CCmdUI* pCmdUI)
{
	pCmdUI->Enable(CURRENT_DIALECT_VIEW != NULL);
}

void CMainFrame::OnFileOpen()
{
	static TCHAR filter[] =
		_T("Dialect Files (*.d)\0*.d\0")
		_T("Layout Files (*.lyo)\0*.lyo\0")
		_T("Text Files (*.txt)\0*.txt\0")
		_T("All Files (*.*)\0*.*\0\0");

	TCHAR _FullPath[MAX_PATH];
	memset(_FullPath, 0, MAX_PATH * sizeof(TCHAR));

	OPENFILENAME ofn;
	memset(&ofn, 0, sizeof(OPENFILENAME));
	ofn.lStructSize = sizeof(OPENFILENAME);
	ofn.hwndOwner = GetSafeHwnd();
	ofn.hInstance = AfxGetInstanceHandle();
	ofn.lpstrFilter = filter;
	ofn.nFilterIndex = 1;
	ofn.lpstrFile = _FullPath;
	ofn.nMaxFile = MAX_PATH;
	ofn.Flags = OFN_FILEMUSTEXIST | OFN_HIDEREADONLY;
	ofn.lpstrDefExt = _T("d");

	if (GetOpenFileName(&ofn)) {
		CString fullPath = _FullPath;//dlg.GetPathName();
		CString filename;// = dlg.GetFileName();
		CString directory;// = fullPath.Left(fullPath.GetLength() - filename.GetLength());
		SplitFullPath(fullPath, directory, filename);	// CE dlg is lacking...
		OpenFile(directory, filename);
	}
}

bool CMainFrame::OpenFile(CString directory, CString filename)
{
	CDialectView* pChild = (CDialectView*)g_FilenameToView[directory + filename].Integer();
	if (pChild != NULL) {
		MessageBox(_T("This file is already open..."));
		ActivateDialectView(pChild);
		return true;
	}
	else {
		pChild = NewDialectView();
		if ((pChild != NULL) && !pChild->Open(directory, filename)) {
			delete pChild;
			return false;
		}
		else {
			ActivateDialectView(pChild);
			AfxGetApp()->AddToRecentFileList(directory + filename);
			UpdateWindowMenu();
			return true;
		}
	}
}

void CMainFrame::New()
{
	OnFileNew();
}

void CMainFrame::OnFileNew()
{
	CDialectView* pChild = NewDialectView();
	g_ModNameToView.Set(pChild->GetModuleName(), (int)pChild);
	UpdateWindowMenu();
}

void CMainFrame::OnFilePrint()
{
#ifdef UNDER_CE
	MessageBox(_T("Printing is not supported in this version of Dialect"));
#else
	CDialectView* pChild = CURRENT_DIALECT_VIEW;
	if (pChild == NULL) return;

	CPrintDialog dlg(FALSE);
	if (dlg.DoModal() == IDOK) {
		pChild->Print(dlg.m_pd.hDC);
		::DeleteDC(dlg.m_pd.hDC);
	}
#endif
}

void CMainFrame::OnUpdateFilePrint(CCmdUI* pCmdUI)
{
	pCmdUI->Enable(CURRENT_DIALECT_VIEW != NULL);
}

bool CMainFrame::SaveAllButCurrentView()
{
	CDialectView* pCurrent = CURRENT_DIALECT_VIEW;

	VALUE key, value;
	FindNextInfo fni;
	while (g_FilenameToView.FindNext(fni, key, value)) {
		CDialectView* pChild = (CDialectView*)value.Integer();
		bool bPrompt = !m_bSaveAllOnRun;	// Auto save everything without asking
		if ((pChild != NULL) && (m_bSaveAllOnRun || (pChild != pCurrent))) {
			if (!pChild->Save(bPrompt)) return false;	// User canceled
		}
	}
	return true;
}

void CMainFrame::DisplayError(VALUE vException)
{
	VALUE vCallstack = vException[_T("callstack")];

	CString cr = _T("\r\n");
	CString msg = vException[_T("msg")].String();
	CString module = vException[_T("module")].String();
	CString line = _T("Line: ") + vException[_T("line")].String();
	CString callstack = _T("Callstack: ") + vCallstack.String();

	int iLine = vException[_T("line")].Integer();
	if ((iLine == 0) && (vCallstack.Type() == stArray)) {
		// In core module, so we can't open the code in a window,
		// so work up the callstack until we reach a non-core module.
		VALUE vTemp;
		for (int idx = vCallstack.Length() - 1; idx > 0; --idx) {
			vTemp = vCallstack[idx];
			if (vTemp[2].Integer() > 0) {
				FlashLine(vTemp[1].String(), vTemp[2].Integer(), RGB(255, 64, 64));
				break;
			}
		}
	}
	else {
		FlashLine(module, iLine, RGB(255, 64, 64));
	}

	CString err = msg + cr + _T("Module: ") + module + cr + line + cr + callstack;
	MessageBox(err, _T("Error"), MB_OK);
}

void CMainFrame::FlashLine(CString module, int line, COLORREF color)
{
	CDialectView* pChild = (CDialectView*)g_ModNameToView.Get(module).Integer();
	if ((pChild != NULL) && ::IsWindow(pChild->m_hWnd)) {
		ActivateDialectView(pChild);
		pChild->FlashLine(line - 1, color);
	}
}

void CMainFrame::OnSetFocus(CWnd* pOldWnd)
{
	ActivateDialectView(CURRENT_DIALECT_VIEW);
}

void CMainFrame::OnActivate(UINT nState, CWnd* pWndOther, BOOL bMinimized)
{
	BASEFRAMEWND::OnActivate(nState, pWndOther, bMinimized);

	if (nState != WA_INACTIVE) {
		ActivateDialectView(CURRENT_DIALECT_VIEW);
	}
}

void CMainFrame::OnKeyDown(UINT nChar, UINT nRepCnt, UINT nFlags)
{
	BASEFRAMEWND::OnKeyDown(nChar, nRepCnt, nFlags);
}

void CMainFrame::OnWindowNext()
{
#ifdef __MDI__
	ASSERT(false);	// The MDI version shouldn't have accelerators for this!
#else
	if (!m_DialectViewList.IsEmpty()) {
		CDialectView* pView = CURRENT_DIALECT_VIEW;
		POSITION p = pView == NULL ? NULL : m_DialectViewList.Find(pView);
		if (p == NULL) {
			ActivateDialectView((CDialectView*)m_DialectViewList.GetHead());
		}
		else {
			// Go forwards in list
			m_DialectViewList.GetNext(p);
			if (p == NULL) {
				p = m_DialectViewList.GetHeadPosition();
			}
			ActivateDialectView((CDialectView*)m_DialectViewList.GetAt(p));
		}
	}
	else m_pCurrentDialectView = NULL;
#endif
}

void CMainFrame::OnWindowPrevious()
{
#ifdef __MDI__
	ASSERT(false);	// The MDI version shouldn't have accelerators for this!
#else
	if (!m_DialectViewList.IsEmpty()) {
		CDialectView* pView = CURRENT_DIALECT_VIEW;
		POSITION p = pView == NULL ? NULL : m_DialectViewList.Find(pView);
		if (p == NULL) {
			ActivateDialectView((CDialectView*)m_DialectViewList.GetTail());
		}
		else {
			// Go backwards in list
			m_DialectViewList.GetPrev(p);
			if (p == NULL) {
				p = m_DialectViewList.GetTailPosition();
			}
			ActivateDialectView((CDialectView*)m_DialectViewList.GetAt(p));
		}
	}
	else m_pCurrentDialectView = NULL;
#endif
}

void CMainFrame::UpdateWindowMenu()
{
#ifndef __MDI__
	UINT idx;

	// Get the pointer to the Window menu so we can add and delete
	// the list of open windows
	CMenu* pMenu = GetMenu();
	ASSERT(pMenu != NULL);
	for (idx = 0; idx < pMenu->GetMenuItemCount() - 1; ++idx) {
		CMenu* pTemp = pMenu->GetSubMenu(idx);
		if (pTemp && pTemp->GetMenuItemID(0) == ID_WINDOW_NEXT) {
			pMenu = pTemp;
			break;
		}
	}

	// Delete all items except top three (Next, Previous, and seperator)
	for (idx = pMenu->GetMenuItemCount() - 1; idx > 2; --idx) {
		pMenu->DeleteMenu(idx, MF_BYPOSITION);
	}

	// Now add the list of window names...
	CDialectView* pView;
	int id = ID_WINDOW_FIRST;
	POSITION p = m_DialectViewList.GetHeadPosition();
	while (p != NULL) {
		if (id > ID_WINDOW_LAST) break;	// Don't have handlers past this!
		pView = (CDialectView*)m_DialectViewList.GetNext(p);
		pMenu->AppendMenu(MF_STRING | MF_ENABLED, id++, pView->GetModuleName());
	}

	// This is also not a bad place to make sure the
	// window title is correct since this func is called
	// after a load, save, new, etc.
	pView = CURRENT_DIALECT_VIEW;
	if (pView != NULL) SetWindowText(pView->GetModuleName());
	else SetWindowText(_T("Dialect"));
#endif
}

void CMainFrame::OnWindowSelect(UINT id)
{
#ifndef __MDI__
	POSITION p = m_DialectViewList.FindIndex(id - ID_WINDOW_FIRST);
	if (p != NULL) {
		ActivateDialectView((CDialectView*)m_DialectViewList.GetAt(p));
	}
#endif
}

void CMainFrame::OnViewLineNumbers()
{
	// Loop through all views
	bool bShow;
	VALUE key, value;
	FindNextInfo fni;
	while (g_ModNameToView.FindNext(fni, key, value)) {
		CDialectView* pView = (CDialectView*)value.Integer();
		if (pView != NULL) {
			bShow = !pView->GetShowLineNumbers();
			pView->SetShowLineNumbers(bShow);
		}
	}
	AfxGetApp()->WriteProfileInt(_T("Options"), _T("ShowLineNums"), bShow ? 1 : 0);
}

void CMainFrame::OnUpdateViewLineNumbers(CCmdUI* pCmdUI)
{
	// Since we currently do this all or nothing, checking one
	// view will tell us what we want to know...
	CDialectView* pView = CURRENT_DIALECT_VIEW;
	if (pView != NULL) {
		pCmdUI->SetCheck(pView->GetShowLineNumbers());
	}
	else {
		pCmdUI->SetCheck(AfxGetApp()->GetProfileInt(_T("Options"), _T("ShowLineNums"), true));
	}
}

void CMainFrame::OnProjectAutosaveallonrun()
{
	m_bSaveAllOnRun = !m_bSaveAllOnRun;
	AfxGetApp()->WriteProfileInt(_T("Options"), _T("SaveAllOnRun"), m_bSaveAllOnRun ? 1 : 0);
}

void CMainFrame::OnUpdateProjectAutosaveallonrun(CCmdUI* pCmdUI)
{
	pCmdUI->SetCheck(m_bSaveAllOnRun);
}

void CMainFrame::OnProjectCleardefaultmainmodule()
{
	m_MainModule.Empty();
	AfxGetApp()->WriteProfileString(_T("Options"), _T("LastMainModule"), _T(""));
}

void CMainFrame::OnUpdateProjectCleardefaultmainmodule(CCmdUI* pCmdUI)
{
	pCmdUI->Enable(!m_MainModule.IsEmpty());
}

void CMainFrame::OnProjectSetdefaultmainmodule()
{
	CDialectView* pView = CURRENT_DIALECT_VIEW;
	if (pView != NULL) {
		m_MainModule = pView->GetModuleName();
		CString temp = _T("The main module has been set to '") + m_MainModule +	_T("'.");
		MessageBox(temp);
		AfxGetApp()->WriteProfileString(_T("Options"), _T("LastMainModule"), m_MainModule);
	}
}

void CMainFrame::OnUpdateProjectSetdefaultmainmodule(CCmdUI* pCmdUI)
{
	pCmdUI->Enable(CURRENT_DIALECT_VIEW != NULL);
}

void CMainFrame::OnFileSaveall()
{
	VALUE key, value;
	FindNextInfo fni;
	while (g_ModNameToView.FindNext(fni, key, value)) {
		CDialectView* pChild = (CDialectView*)value.Integer();
		if (pChild) {
			if (pChild->GetFilename().IsEmpty()) {
				// No file name yet, bring it to the front so
				// the user knows which file they are being requested
				// to name
				ActivateDialectView(pChild);
			}
			pChild->Save(false);
		}
	}
}

void CMainFrame::OnProjectMakeexe()
{
#ifdef DIALECT_LITE
	MessageBox(_T("Make EXE is unsupported in Dialect Lite"));
#else
	CDialectView* pView = CURRENT_DIALECT_VIEW;

	// We need to request a save first...
	VALUE key, value;
	FindNextInfo fni;
	while (g_ModNameToView.FindNext(fni, key, value)) {
		CDialectView* pChild = (CDialectView*)value.Integer();
		if (pChild) {
			if (pChild->GetFilename().IsEmpty()) {
				// No file name yet, bring it to the front so
				// the user knows which file they are being requested
				// to name
				ActivateDialectView(pChild);
			}
			if (!pChild->Save(true)) return;
		}
	}

	CString module = m_MainModule;
	if (g_ModNameToView.Get(module).Integer() == 0) {
		module.Empty();
	}

	if (module.IsEmpty()) {
		if (pView != NULL) {
			module = pView->GetFilename();
		}
	}

	CString directory;
	int pos = module.ReverseFind('\\');
	if (pos > 0) {
		directory = module.Left(pos + 1);
	}

	CMakeExeDlg dlg(this);
	dlg.m_InitialModule = module;
	dlg.m_SourceDir = directory;
	dlg.DoModal();
#endif // DIALECT_LITE
}

///////////////////////////////////////////////////////////////////

void CMainFrame::OnEditCopy()
{
	CDialectView* pView = CURRENT_DIALECT_VIEW;
	if (pView) pView->OnEditCopy();
}

void CMainFrame::OnUpdateEditCopy(CCmdUI* pCmdUI)
{
	pCmdUI->Enable(CURRENT_DIALECT_VIEW != NULL);
}

void CMainFrame::OnEditCut()
{
	CDialectView* pView = CURRENT_DIALECT_VIEW;
	if (pView) pView->OnEditCut();
}

void CMainFrame::OnUpdateEditCut(CCmdUI* pCmdUI)
{
	pCmdUI->Enable(CURRENT_DIALECT_VIEW != NULL);
}

void CMainFrame::OnEditDelete()
{
	CDialectView* pView = CURRENT_DIALECT_VIEW;
	if (pView) pView->OnEditDelete();
}

void CMainFrame::OnUpdateEditDelete(CCmdUI* pCmdUI)
{
	pCmdUI->Enable(CURRENT_DIALECT_VIEW != NULL);
}

void CMainFrame::OnEditPaste()
{
	CDialectView* pView = CURRENT_DIALECT_VIEW;
	if (pView) pView->OnEditPaste();
}

void CMainFrame::OnUpdateEditPaste(CCmdUI* pCmdUI)
{
	pCmdUI->Enable(CURRENT_DIALECT_VIEW != NULL);
}

void CMainFrame::OnEditCommentOut()
{
	CDialectView* pView = CURRENT_DIALECT_VIEW;
	if (pView) pView->OnEditCommentOut();
}

void CMainFrame::OnUpdateEditCommentOut(CCmdUI* pCmdUI)
{
	pCmdUI->Enable(CURRENT_DIALECT_VIEW != NULL);
}

void CMainFrame::OnEditUncomment()
{
	CDialectView* pView = CURRENT_DIALECT_VIEW;
	if (pView) pView->OnEditUncomment();
}

void CMainFrame::OnUpdateEditUncomment(CCmdUI* pCmdUI)
{
	pCmdUI->Enable(CURRENT_DIALECT_VIEW != NULL);
}

void CMainFrame::OnEditIndent()
{
	CDialectView* pView = CURRENT_DIALECT_VIEW;
	if (pView) pView->OnEditIndent();
}

void CMainFrame::OnUpdateEditIndent(CCmdUI* pCmdUI)
{
	pCmdUI->Enable(CURRENT_DIALECT_VIEW != NULL);
}

void CMainFrame::OnEditUnindent()
{
	CDialectView* pView = CURRENT_DIALECT_VIEW;
	if (pView) pView->OnEditUnindent();
}

void CMainFrame::OnUpdateEditUnindent(CCmdUI* pCmdUI)
{
	pCmdUI->Enable(CURRENT_DIALECT_VIEW != NULL);
}

void CMainFrame::OnEditRedo()
{
	CDialectView* pView = CURRENT_DIALECT_VIEW;
	if (pView) pView->OnEditRedo();
}

void CMainFrame::OnUpdateEditRedo(CCmdUI* pCmdUI)
{
	CDialectView* pView = CURRENT_DIALECT_VIEW;
	if (pView) pView->OnUpdateEditRedo(pCmdUI);
}

void CMainFrame::OnEditSelectall()
{
	CDialectView* pView = CURRENT_DIALECT_VIEW;
	if (pView) pView->OnEditSelectall();
}

void CMainFrame::OnEditUndo()
{
	CDialectView* pView = CURRENT_DIALECT_VIEW;
	if (pView) pView->OnEditUndo();
}

void CMainFrame::OnUpdateEditUndo(CCmdUI* pCmdUI)
{
	CDialectView* pView = CURRENT_DIALECT_VIEW;
	if (pView) pView->OnUpdateEditUndo(pCmdUI);
}

void CMainFrame::OnProjectInsertbreakpoint()
{
	CDialectView* pView = CURRENT_DIALECT_VIEW;
	if (pView) pView->OnProjectInsertbreakpoint();
}

void CMainFrame::OnViewDebugout()
{
	if (m_DebugOutDlg.IsWindowVisible()) {
		m_DebugOutDlg.ShowWindow(SW_HIDE);
	}
	else {
		m_DebugOutDlg.ShowWindow(SW_SHOW);
		m_DebugOutDlg.BringWindowToTop();
	}
}

void CMainFrame::OnUpdateViewDebugout(CCmdUI* pCmdUI)
{
	pCmdUI->SetCheck(m_DebugOutDlg.IsWindowVisible());
}

/////////////////////////////////////////////////////////
#endif // IDE_SUPPORT